from django.db import transaction
from django.core.exceptions import ValidationError
from django.db.models import Q, F
from .models import Flower, FlowerCategory, FlowerImage, FlowerSpec
from common.utils.oss_utils import FileOss
from common.utils.utils import generate_unique_filename, validate_image_file
import uuid
from datetime import datetime


class FlowerCategoryService:
    """鲜花分类服务"""
    
    @staticmethod
    def get_active_categories():
        """获取启用的分类列表"""
        return FlowerCategory.objects.filter(is_active=True).order_by('sort_order', '-created_at')
    
    @staticmethod
    def create_category(data):
        """创建分类"""
        return FlowerCategory.objects.create(**data)
    
    @staticmethod
    def update_category(category_id, data):
        """更新分类"""
        category = FlowerCategory.objects.get(id=category_id)
        for key, value in data.items():
            setattr(category, key, value)
        category.save()
        return category
    
    @staticmethod
    def delete_category(category_id):
        """删除分类"""
        category = FlowerCategory.objects.get(id=category_id)
        # 检查是否有商品使用此分类
        if category.flower_set.exists():
            raise ValidationError("该分类下还有商品，无法删除")
        category.delete()


class FlowerService:
    """鲜花商品服务"""
    
    @staticmethod
    def get_flower_list(filters=None, ordering=None):
        """获取鲜花列表"""
        queryset = Flower.objects.select_related('category').prefetch_related('images')
        
        if filters:
            if filters.get('category_id'):
                queryset = queryset.filter(category_id=filters['category_id'])
            if filters.get('status'):
                queryset = queryset.filter(status=filters['status'])
            if filters.get('is_featured') is not None:
                queryset = queryset.filter(is_featured=filters['is_featured'])
            if filters.get('search'):
                queryset = queryset.filter(
                    Q(name__icontains=filters['search']) |
                    Q(description__icontains=filters['search'])
                )
            if filters.get('price_min'):
                queryset = queryset.filter(price__gte=filters['price_min'])
            if filters.get('price_max'):
                queryset = queryset.filter(price__lte=filters['price_max'])
        
        if ordering:
            queryset = queryset.order_by(ordering)
        else:
            queryset = queryset.order_by('sort_order', '-created_at')
        
        return queryset
    
    @staticmethod
    def get_flower_detail(flower_id):
        """获取鲜花详情"""
        return Flower.objects.select_related('category').prefetch_related(
            'images', 'specs'
        ).get(id=flower_id)
    
    @staticmethod
    @transaction.atomic
    def create_flower(data):
        """创建鲜花商品"""
        images_data = data.pop('images', [])
        specs_data = data.pop('specs', [])
        
        flower = Flower.objects.create(**data)
        
        # 创建图片
        for i, image_data in enumerate(images_data):
            image_data['sort_order'] = i
            if i == 0:  # 第一张设为主图
                image_data['is_main'] = True
            FlowerImage.objects.create(flower=flower, **image_data)
        
        # 创建规格
        for i, spec_data in enumerate(specs_data):
            spec_data['sort_order'] = i
            FlowerSpec.objects.create(flower=flower, **spec_data)
        
        return flower
    
    @staticmethod
    @transaction.atomic
    def update_flower(flower_id, data):
        """更新鲜花商品"""
        flower = Flower.objects.get(id=flower_id)
        images_data = data.pop('images', None)
        specs_data = data.pop('specs', None)
        
        # 更新基本信息
        for key, value in data.items():
            setattr(flower, key, value)
        flower.save()
        
        # 更新图片
        if images_data is not None:
            flower.images.all().delete()
            for i, image_data in enumerate(images_data):
                image_data['sort_order'] = i
                if i == 0:
                    image_data['is_main'] = True
                FlowerImage.objects.create(flower=flower, **image_data)
        
        # 更新规格
        if specs_data is not None:
            flower.specs.all().delete()
            for i, spec_data in enumerate(specs_data):
                spec_data['sort_order'] = i
                FlowerSpec.objects.create(flower=flower, **spec_data)
        
        return flower
    
    @staticmethod
    def delete_flower(flower_id):
        """删除鲜花商品"""
        flower = Flower.objects.get(id=flower_id)
        # 删除OSS上的图片
        oss_client = FileOss()
        for image in flower.images.all():
            try:
                # 从URL中提取文件路径
                if image.image_url:
                    path = image.image_url.replace('https://flower-1.oss-cn-shanghai.aliyuncs.com/', '')
                    oss_client.del_object(path)
            except Exception:
                pass  # 忽略删除失败的情况
        
        flower.delete()
    
    @staticmethod
    def update_stock(flower_id, quantity, operation='decrease'):
        """更新库存"""
        flower = Flower.objects.select_for_update().get(id=flower_id)
        
        if operation == 'decrease':
            if flower.stock < quantity:
                raise ValidationError("库存不足")
            flower.stock = F('stock') - quantity
        elif operation == 'increase':
            flower.stock = F('stock') + quantity
        
        flower.save()
        flower.refresh_from_db()
        return flower
    
    @staticmethod
    def update_sales_count(flower_id, quantity):
        """更新销售数量"""
        Flower.objects.filter(id=flower_id).update(
            sales_count=F('sales_count') + quantity
        )


class ImageUploadService:
    """图片上传服务"""
    
    @staticmethod
    def upload_image(image_file, folder='flowers'):
        """上传图片到OSS"""
        # 验证图片
        is_valid, message = validate_image_file(image_file)
        if not is_valid:
            raise ValidationError(message)
        
        # 生成唯一文件名
        unique_filename = generate_unique_filename(image_file.name)
        
        # 构建OSS路径
        now = datetime.now()
        oss_path = f"{folder}/{now.year}/{now.month:02d}/{now.day:02d}/{unique_filename}"
        
        # 上传到OSS
        oss_client = FileOss()
        try:
            image_url = oss_client.get_oss_image_url(oss_path, image_file.read())
            if not image_url:
                raise ValidationError("图片上传失败")
            return image_url
        except Exception as e:
            raise ValidationError(f"图片上传失败: {str(e)}")
    
    @staticmethod
    def upload_image_from_url(image_url, filename, folder='flowers'):
        """从URL上传图片到OSS"""
        import requests
        import time
        
        try:
            # 下载图片
            headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
            }
            response = requests.get(image_url, headers=headers, timeout=10)
            response.raise_for_status()
            
            # 生成OSS路径
            timestamp = str(int(time.time()))
            unique_id = str(uuid.uuid4())[:8]
            name, ext = filename.rsplit('.', 1) if '.' in filename else (filename, 'jpg')
            unique_filename = f"{name}_{timestamp}_{unique_id}.{ext}"
            
            now = datetime.now()
            oss_path = f"{folder}/{now.year}/{now.month:02d}/{now.day:02d}/{unique_filename}"
            
            # 上传到OSS
            oss_client = FileOss()
            oss_url = oss_client.get_oss_image_url(oss_path, response.content)
            
            if not oss_url:
                raise ValidationError("图片上传失败")
            
            return oss_url
            
        except requests.RequestException as e:
            raise ValidationError(f"下载图片失败: {str(e)}")
        except Exception as e:
            raise ValidationError(f"上传图片失败: {str(e)}")
    
    @staticmethod
    def delete_image(image_url):
        """删除OSS上的图片"""
        if not image_url:
            return
        
        try:
            # 从URL中提取文件路径
            path = image_url.replace('https://flower-1.oss-cn-shanghai.aliyuncs.com/', '')
            oss_client = FileOss()
            oss_client.del_object(path)
        except Exception:
            pass  # 忽略删除失败的情况


class FlowerSearchService:
    """鲜花搜索服务"""
    
    @staticmethod
    def search_flowers(keyword, filters=None):
        """搜索鲜花"""
        queryset = Flower.objects.filter(status='active')
        
        if keyword:
            queryset = queryset.filter(
                Q(name__icontains=keyword) |
                Q(description__icontains=keyword) |
                Q(category__name__icontains=keyword)
            )
        
        if filters:
            if filters.get('category_id'):
                queryset = queryset.filter(category_id=filters['category_id'])
            if filters.get('price_min'):
                queryset = queryset.filter(price__gte=filters['price_min'])
            if filters.get('price_max'):
                queryset = queryset.filter(price__lte=filters['price_max'])
        
        return queryset.select_related('category').prefetch_related('images')
    
    @staticmethod
    def get_hot_flowers(limit=10):
        """获取热门鲜花"""
        return Flower.objects.filter(
            status='active'
        ).order_by('-sales_count', '-created_at')[:limit]
    
    @staticmethod
    def get_featured_flowers(limit=10):
        """获取推荐鲜花"""
        return Flower.objects.filter(
            status='active',
            is_featured=True
        ).order_by('sort_order', '-created_at')[:limit]